package cn.getech.data.development.utils;

import cn.getech.data.development.model.vo.UdfJarPropertyVo;
import cn.getech.data.intelligence.common.exception.RRException;
import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * \* AUTH: HQZ
 * \* Date: 2019/12/11
 * \* Time: 11:40
 * \* Description:
 * \
 */
@Slf4j
public class JarParseUtil {


    /**
     * 这些默认方法不打印
     */
    private static String DEFAULT_METHOD = "waitequalsnotifynotifyAlltoStringhashCodegetClass";


    private static void getJarName(String jarFile) throws Exception {
        try{
            //通过将给定路径名字符串转换为抽象路径名来创建一个新File实例
            File f = new File(jarFile);
            URL url1 = f.toURI().toURL();
            URLClassLoader myClassLoader = new URLClassLoader(new URL[]{url1},Thread.currentThread().getContextClassLoader());

            //通过jarFile和JarEntry得到所有的类
            JarFile jar = new JarFile(jarFile);
            //返回zip文件条目的枚举
            Enumeration<JarEntry> enumFiles = jar.entries();
            JarEntry entry;

            //测试此枚举是否包含更多的元素
            while(enumFiles.hasMoreElements()){
                entry = (JarEntry)enumFiles.nextElement();
                if(entry.getName().indexOf("META-INF")<0){
                    String classFullName = entry.getName();
                    if(!classFullName.endsWith(".class")){
                        classFullName = classFullName.substring(0,classFullName.length()-1);
                    } else{
                        //去掉后缀.class
                        String className = classFullName.substring(0,classFullName.length()-6).replace("/", ".");
                        Class<?> myclass = myClassLoader.loadClass(className);
                        //打印类名
                        System.out.println("*****************************");
                        System.out.println("全类名:" + className);

                        //得到类中包含的属性
                        Method[] methods = myclass.getMethods();
                        for (Method method : methods) {
                            String methodName = method.getName();
                            System.out.println("方法名称:" + methodName);
                            Class<?>[] parameterTypes = method.getParameterTypes();
                            for (Class<?> clas : parameterTypes) {
                                // String parameterName = clas.getName();
                                String parameterName = clas.getSimpleName();
                                System.out.println("参数类型:" + parameterName);
                            }
                            System.out.println("==========================");
                        }
                    }
                }
            }
        } catch(IOException e){
            e.printStackTrace();
        }
    }


    public static List<UdfJarPropertyVo> getJarClassAndFuncs(File file, List<String> packUrls) throws Exception {
        List<UdfJarPropertyVo> jarDetails = new ArrayList<>();
        try{
            //通过将给定路径名字符串转换为抽象路径名来创建一个新File实例
            URL url1 = file.toURI().toURL();
            URLClassLoader myClassLoader = new URLClassLoader(new URL[]{url1},Thread.currentThread().getContextClassLoader());

            //通过jarFile和JarEntry得到所有的类
            JarFile jar = new JarFile(file);
            //返回zip文件条目的枚举
            Enumeration<JarEntry> enumFiles = jar.entries();
            JarEntry entry;
            //测试此枚举是否包含更多的元素
            while(enumFiles.hasMoreElements()){
                entry = (JarEntry)enumFiles.nextElement();
                if(!entry.getName().contains("META-INF")){
                    String classFullName = entry.getName();
                    if(!classFullName.endsWith(".class")){
                        classFullName = classFullName.substring(0,classFullName.length()-1);
                    } else{
                        //去掉后缀.class
                        String className = classFullName.replace("/", ".");
                        if (startsWithLists(className,packUrls)) {//解析自己内部类
                            //得到类中包含的属性
                            try {
                                Class<?> myclass = myClassLoader.loadClass(className);
                                Method[] methods = myclass.getMethods();
                                for (Method method : methods) {
                                    String methodName = method.getName();
                                    UdfJarPropertyVo udfJarPropertyVo = new UdfJarPropertyVo();
                                    udfJarPropertyVo.setJarClassName(className);
                                    udfJarPropertyVo.setJarMethodName(methodName);
                                    jarDetails.add(udfJarPropertyVo);
                                    log.info("\n内部类已经解析:{}:{}", className, methodName);
                                }
                            } catch (Exception e) {
                                log.warn("类解析失败:", e);
                            }
                        }else{
                            throw new RRException("请联系租户管理员前往数据字典中配置UDF_dirpath!",500);
                        }
                    }
                }
            }
        } catch(IOException e){
            e.printStackTrace();
        }
        return jarDetails;
    }

    private static boolean startsWithLists(String className, List<String> packUrls) {
        if(CollectionUtil.isNotEmpty(packUrls)){
            for (String packUrl : packUrls) {
                if(className.startsWith(packUrl)){
                    return true;
                }
            }
        }
        return false;
    }


    public static void main(String[] args) throws Exception {
        //jar包所在路径
            /*getJarName("F:\\user.jar");
            getJarName("F:\\role1.jar");
            getJarName("F:\\role2.jar"); */
        //getJarName("F:\\UserInfo.jar");
        getJarName("E:\\bdp-web\\bdp-admin\\udf\\datamg-hive-udf-1.0.jar");

    }

}
